package cn.iocoder.yudao.module.system.service.partner;

import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.api.coupon.CouponTemplateApi;
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponTemplateReqDTO;
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponTemplateRespDTO;
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
import cn.iocoder.yudao.module.system.api.partner.dto.PartnerReqDTO;
import cn.iocoder.yudao.module.system.api.partner.dto.PartnerSendReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.partner.vo.PartnerPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.partner.vo.PartnerSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.partnerstore.vo.PartnerStoreSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.dataobject.partner.PartnerDO;
import cn.iocoder.yudao.module.system.dal.dataobject.partnercoupon.PartnerCouponDO;
import cn.iocoder.yudao.module.system.dal.dataobject.partnerstore.PartnerStoreDO;
import cn.iocoder.yudao.module.system.dal.mysql.partner.PartnerMapper;
import cn.iocoder.yudao.module.system.dal.mysql.partnercoupon.PartnerCouponMapper;
import cn.iocoder.yudao.module.system.dal.mysql.partnerstore.PartnerStoreMapper;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import cn.iocoder.yudao.module.trade.api.store.StoreApi;
import cn.iocoder.yudao.module.trade.api.store.dto.StoreRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.PARTNER_NOT_EXISTS;

/**
 * 合伙人 Service 实现类
 *
 * @author 万民匠心
 */
@Service
@Validated
@Slf4j
public class PartnerServiceImpl implements PartnerService {

    @Resource
    private PartnerMapper partnerMapper;
    @Resource
    private DictDataService dictDataService;
    @Resource
    private PartnerStoreMapper partnerStoreMapper;
    @Resource
    private PartnerCouponMapper partnerCouponMapper;
    @Resource
    private CouponTemplateApi couponTemplateApi;
    @Resource
    private StoreApi storeApi;

    @Override
    public Long createPartner(PartnerSaveReqVO createReqVO) {
        // 插入
        PartnerDO partner = BeanUtils.toBean(createReqVO, PartnerDO.class);

        checkExist(createReqVO);

        partnerMapper.insert(partner);

        if (!CollectionUtils.isAnyEmpty(createReqVO.getStoreList())) {
            List<PartnerStoreDO> partnerStoreList = BeanUtils.toBean(createReqVO.getStoreList(), PartnerStoreDO.class);
            partnerStoreList.forEach(item -> {
                item.setPartnerId(partner.getId());
                item.setCreateTime(partner.getCreateTime());
                item.setCreator(partner.getCreator());
                item.setUpdater(partner.getUpdater());
                item.setUpdateTime(partner.getUpdateTime());
            });
            partnerStoreMapper.insertBatch(partnerStoreList);
        }

//        if (!CollectionUtils.isAnyEmpty(createReqVO.getCouponList())) {
//            List<PartnerCouponDO> partnerCouponList = BeanUtils.toBean(createReqVO.getCouponList(), PartnerCouponDO.class);
//            partnerCouponList.forEach(item -> {
//                item.setPartnerId(partner.getId());
//                item.setCreateTime(partner.getCreateTime());
//                item.setCreator(partner.getCreator());
//                item.setUpdater(partner.getUpdater());
//                item.setUpdateTime(partner.getUpdateTime());
//            });
//            partnerCouponMapper.insertBatch(partnerCouponList);
//        }
        // 返回
        return partner.getId();
    }

    private void checkExist(PartnerSaveReqVO createReqVO) {
        if (!CollectionUtils.isAnyEmpty(createReqVO.getStoreList())) {
            List<StoreRespDTO> storeList = storeApi.getStoreList(convertSet(createReqVO.getStoreList(), PartnerStoreSaveReqVO::getStoreId));
            Map<Long, StoreRespDTO> storeMap = convertMap(storeList, StoreRespDTO::getId);
            createReqVO.getStoreList().forEach(item -> {
                if (1 == item.getPartnerType()) {
                    List<PartnerStoreDO> partnerStoreList = partnerStoreMapper.selectList(new LambdaQueryWrapperX<PartnerStoreDO>()
                            .eq(PartnerStoreDO::getStoreId, item.getStoreId()).eq(PartnerStoreDO::getPartnerType, 1)
                            .eq(PartnerStoreDO::getDeleted, Boolean.FALSE));
                    if (Objects.isNull(createReqVO.getId())) {
                        if (!CollectionUtils.isAnyEmpty(partnerStoreList)) {
                            throw exception(new ErrorCode(1_002_008_007, String.format("【%s】已有发起合伙人", storeMap.get(item.getStoreId()).getName())));
                        }
                    } else {
                        List<PartnerStoreDO> hasExistList = partnerStoreList.stream().filter(store -> !store.getPartnerId().equals(createReqVO.getId())).collect(Collectors.toList());
                        if (!CollectionUtils.isAnyEmpty(hasExistList)) {
                            throw exception(new ErrorCode(1_002_008_007, String.format("【%s】已有发起合伙人", storeMap.get(item.getStoreId()).getName())));
                        }
                    }
                }
            });
        }
    }

    @Override
    public void updatePartner(PartnerSaveReqVO updateReqVO) {
        // 校验存在
        validatePartnerExists(updateReqVO.getId());

        checkExist(updateReqVO);

        // 更新
        PartnerDO updateObj = BeanUtils.toBean(updateReqVO, PartnerDO.class);
        partnerMapper.updateById(updateObj);


        // 查询已存在数据
        List<PartnerStoreDO> deleteStoreList = partnerStoreMapper.selectList(new LambdaQueryWrapperX<PartnerStoreDO>()
                .eq(PartnerStoreDO::getPartnerId, updateReqVO.getId()).eq(PartnerStoreDO::getDeleted, Boolean.FALSE));

//        List<PartnerCouponDO> deleteCouponList = partnerCouponMapper.selectList(new LambdaQueryWrapperX<PartnerCouponDO>()
//                .eq(PartnerCouponDO::getPartnerId, updateReqVO.getId()).eq(PartnerCouponDO::getDeleted, Boolean.FALSE));

        if (!CollectionUtils.isAnyEmpty(updateReqVO.getStoreList())) {
            List<PartnerStoreDO> partnerStoreList = BeanUtils.toBean(updateReqVO.getStoreList(), PartnerStoreDO.class);
            List<PartnerStoreDO> insertList = Lists.newArrayList();
            List<PartnerStoreDO> updateList = Lists.newArrayList();
            List<Long> updateIds = partnerStoreList.stream().filter(item -> Objects.nonNull(item.getId())).map(item -> item.getId()).collect(Collectors.toList());
            if (!CollectionUtils.isAnyEmpty(updateIds) && !CollectionUtils.isAnyEmpty(deleteStoreList)) {
                deleteStoreList = deleteStoreList.stream().filter(item -> !updateIds.contains(item.getId())).collect(Collectors.toList());
            }
            partnerStoreList.forEach(item -> {
                item.setPartnerId(updateObj.getId());
                item.setUpdater(updateObj.getUpdater());
                item.setUpdateTime(updateObj.getUpdateTime());
                if (Objects.isNull(item.getId())) {
                    item.setCreateTime(updateObj.getCreateTime());
                    item.setCreator(updateObj.getCreator());
                    insertList.add(item);
                } else {
                    updateList.add(item);
                }
            });
            if (!CollectionUtils.isAnyEmpty(insertList)) {
                partnerStoreMapper.insertBatch(insertList);
            }
            if (!CollectionUtils.isAnyEmpty(updateList)) {
                partnerStoreMapper.updateBatch(updateList);
            }
        }

        if (!CollectionUtils.isAnyEmpty(deleteStoreList)) {
            partnerStoreMapper.deleteBatchIds(deleteStoreList.stream().map(item -> item.getId()).collect(Collectors.toList()));
        }

//        if (!CollectionUtils.isAnyEmpty(updateReqVO.getCouponList())) {
//            List<PartnerCouponDO> partnerCouponList = BeanUtils.toBean(updateReqVO.getCouponList(), PartnerCouponDO.class);
//            List<PartnerCouponDO> insertList = Lists.newArrayList();
//            List<PartnerCouponDO> updateList = Lists.newArrayList();
//            List<Long> updateIds = partnerCouponList.stream().filter(item -> Objects.nonNull(item.getId())).map(item -> item.getId()).collect(Collectors.toList());
//            if (!CollectionUtils.isAnyEmpty(updateIds) && !CollectionUtils.isAnyEmpty(deleteCouponList)) {
//                deleteCouponList = deleteCouponList.stream().filter(item -> !updateIds.contains(item.getId())).collect(Collectors.toList());
//            }
//            partnerCouponList.forEach(item -> {
//                item.setPartnerId(updateObj.getId());
//                item.setUpdater(updateObj.getUpdater());
//                item.setUpdateTime(updateObj.getUpdateTime());
//                if (Objects.isNull(item.getId())) {
//                    item.setCreateTime(updateObj.getCreateTime());
//                    item.setCreator(updateObj.getCreator());
//                    insertList.add(item);
//                } else {
//                    updateList.add(item);
//                }
//            });
//            if (!CollectionUtils.isAnyEmpty(insertList)) {
//                partnerCouponMapper.insertBatch(insertList);
//            }
//            if (!CollectionUtils.isAnyEmpty(updateList)) {
//                partnerCouponMapper.updateBatch(updateList);
//            }
//        }
//
//        if (!CollectionUtils.isAnyEmpty(deleteCouponList)) {
//            partnerCouponMapper.deleteBatchIds(deleteCouponList.stream().map(item -> item.getId()).collect(Collectors.toList()));
//        }
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        // 校验用户存在
        validatePartnerExists(id);
        // 更新状态
        PartnerDO updateObj = new PartnerDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        partnerMapper.updateById(updateObj);
    }

    @Override
    public void deletePartner(Long id) {
        // 校验存在
        validatePartnerExists(id);
        // 删除
        partnerMapper.deleteById(id);
    }

    private void validatePartnerExists(Long id) {
        if (partnerMapper.selectById(id) == null) {
            throw exception(PARTNER_NOT_EXISTS);
        }
    }

    @Override
    public PartnerDO getPartner(Long id) {
        return partnerMapper.selectById(id);
    }

    @Override
    public PageResult<PartnerDO> getPartnerPage(PartnerPageReqVO pageReqVO) {
        return partnerMapper.selectPage(pageReqVO);
    }

    @Override
    public List<PartnerDO> getList(PartnerPageReqVO pageReqVO) {
        return partnerMapper.selectList(new LambdaQueryWrapperX<PartnerDO>().eqIfPresent(PartnerDO::getPhone, pageReqVO.getPhone())
                .eqIfPresent(PartnerDO::getStatus, pageReqVO.getStatus())
                .eq(PartnerDO::getDeleted, Boolean.FALSE));
    }

    @Override
    public List<PartnerDO> getListApi(PartnerReqDTO reqVO) {
        return partnerMapper.selectList(new LambdaQueryWrapperX<PartnerDO>()
                .likeIfPresent(PartnerDO::getName, reqVO.getName())
                .likeIfPresent(PartnerDO::getPhone, reqVO.getPhone())
                .eqIfPresent(PartnerDO::getDeleted, reqVO.getStatus()));
    }

    @Override
    public List<PartnerDO> getLpList() {
        List<PartnerStoreDO> partnerStoreList = partnerStoreMapper.selectList(new LambdaQueryWrapperX<PartnerStoreDO>()
                .eqIfPresent(PartnerStoreDO::getPartnerType, 1)
                .eq(PartnerStoreDO::getDeleted, Boolean.FALSE));
        if (CollectionUtils.isAnyEmpty(partnerStoreList)) {
            return Collections.emptyList();
        }

        List<Long> partnerIds = partnerStoreList.stream().map(PartnerStoreDO::getPartnerId).collect(Collectors.toList());
        List<PartnerDO> partnerList = partnerMapper.selectList(new LambdaQueryWrapperX<PartnerDO>()
                .inIfPresent(PartnerDO::getId, partnerIds)
                .eqIfPresent(PartnerDO::getStatus, 1)// 已启用
                .eq(PartnerDO::getDeleted, Boolean.FALSE));

        return partnerList;
    }

    @Override
    public List<PartnerDO> getListByIds(List<Long> partnerIds) {
        return partnerMapper.selectBatchIds(partnerIds);
    }

    @Override
    public int sendPartnerCoupon(PartnerSendReqDTO sendReqDTO) {
        CouponTemplateReqDTO reqDTO = new CouponTemplateReqDTO();
        reqDTO.setTakeType(CouponTakeTypeEnum.PARTNER.getValue());// 分享券
        reqDTO.setStatus(CommonStatusEnum.ENABLE.getStatus());//开启

        List<DictDataDO> couponSettingList = dictDataService.getDictDataList(CommonStatusEnum.ENABLE.getStatus(), DictTypeConstants.PARTNER_COUPON_SETTING);
        DictDataDO limitData = dictDataService.parseDictData(DictTypeConstants.PARTNER_COUPON_LIMIT, DictTypeConstants.PARTNER_COUPON_LIMIT_LABEL);
        if (Objects.isNull(limitData)) {
            log.error("请先设置合伙人优惠券分享限领数量!");
            return 0;
        }

        Integer limitCount = Integer.valueOf(limitData.getValue());


        if (CollectionUtils.isAnyEmpty(couponSettingList)) {
            return 0;
        }
        Map<String, String> setttingMap = couponSettingList.stream().collect(Collectors.toMap(DictDataDO::getLabel, DictDataDO::getValue));

        // 获取合伙人分享券配置
        List<Long> templateIds = couponSettingList.stream().map(DictDataDO::getLabel).collect(Collectors.toList()).stream()
                .map(Long::parseLong)
                .collect(Collectors.toList());

        // 获取合伙人列表
        List<PartnerDO> partnerList = partnerMapper.selectList(new LambdaQueryWrapperX<PartnerDO>()
                .eqIfPresent(PartnerDO::getStatus, 1)
                .orderByDesc(PartnerDO::getId));

        LocalDateTime dateTime = LocalDateTime.now();
        // 生效月份
        String equityMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
        List<Long> hasSendList = partnerCouponMapper.selectHasSendList(dateTime);
        if (Objects.nonNull(sendReqDTO) && !CollectionUtils.isAnyEmpty(sendReqDTO.getPartnerIds())) {
            partnerList = partnerList.stream().filter(item -> sendReqDTO.getPartnerIds().contains(item.getId())).collect(Collectors.toList());
        }
        if (CollectionUtils.isAnyEmpty(partnerList)) {
            return 0;
        }
        if (!CollectionUtils.isAnyEmpty(hasSendList)) {
            partnerList = partnerList.stream().filter(item -> !hasSendList.contains(item.getId())).collect(Collectors.toList());
        }
        if (CollectionUtils.isAnyEmpty(partnerList)) {
            log.info("暂无合伙人需要发送优惠！");
            return 0;
        }

        // 2、查询合伙人分享优惠券
        List<CouponTemplateRespDTO> couponTemplateList = couponTemplateApi.getCouponTemplateList(templateIds);
        if (CollectionUtils.isAnyEmpty(couponTemplateList)) {
            return 0;
        }

        List<PartnerCouponDO> partnerCouponList = Lists.newArrayList();

        partnerList.forEach(partner -> {
            couponTemplateList.forEach(coupon -> {
                PartnerCouponDO partnerCoupon = new PartnerCouponDO();
                partnerCoupon.setPartnerId(partner.getId());
                partnerCoupon.setEquityMonth(equityMonth);
                partnerCoupon.setTemplateId(coupon.getId());
                partnerCoupon.setName(coupon.getName());
                partnerCoupon.setStatus(CommonStatusEnum.ENABLE.getStatus());
                LocalDateTime starTime = LocalDateTime.now().with(LocalTime.MIN);
                LocalDateTime endTime = LocalDateTime.now().with(LocalTime.MAX).plusMonths(1).minusDays(1).withNano(0);
                partnerCoupon.setStartTime(starTime);
                partnerCoupon.setEndTime(endTime);
                String totalCount = setttingMap.get(coupon.getId().toString());
                partnerCoupon.setTotalCount(Integer.valueOf(totalCount));
                partnerCoupon.setLimitCount(limitCount);
                partnerCouponList.add(partnerCoupon);
            });
        });

        partnerCouponMapper.insertBatch(partnerCouponList);
        return partnerList.size();
    }

    @Override
    public Long updatePartnerAmount(PartnerSendReqDTO reqDTO) {
        PartnerDO partnerDO = partnerMapper.selectById(reqDTO.getPartnerId());
        if (Objects.nonNull(reqDTO) && reqDTO.getAmountType() == 1) {
            partnerDO.setTotalProfitAmount(reqDTO.getAmount());//收益总额
        } else {
            partnerDO.setTotalCashoutAmount(reqDTO.getAmount()); //提现总额
        }
        return Long.valueOf(partnerMapper.updateById(partnerDO));
    }

}